﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using Wicture.DbRESTFul.SQL;
using Wicture.EPC.Common;
using Wicture.EPC.Service.V1.Models;
using Wicture.EPC.Service.V1.Repository;

namespace Wicture.EPC.Service.V1.QueryInterceptors.Interceptors
{
    public class BjhdQueryInterceptor : BaseQueryInterceptor
    {
        private string[] brandCodes = new string[] { "bjhd" };

        public override string[] BrandCodes => brandCodes;

        public override object QueryPartDetail(DbRESTFulRepository repository, JObject param)
        {
            param.RemoveEmptyValues();
            var brandCode = param.Value<string>(ParamFields._brandCode);
            var partId = param.Value<string>(ParamFields._partId);
            dynamic data = null;
            if (string.IsNullOrEmpty(partId))
            {
                data = repository.Invoke(CSIs.Get_Part_Detail_For_Bjhd, param);
            }
            else
            {
                data = repository.Invoke(CSIs.Get_Usage_Detail_For_Bjhd, param);
            }
            if (data == null) return null;
            // 1、基本信息赋值
            Query_Part_DetailResult result = JObject.FromObject(data).ToObject<Query_Part_DetailResult>();

            //4.配件附加属性处理
            var props = new List<Query_Part_DetailResult._prop>
            {
                new Query_Part_DetailResult._prop { key = "件数", value = result.quantity ?? string.Empty },
                new Query_Part_DetailResult._prop { key = "英文名称", value = result.partNameEn ?? string.Empty },
            };
            result.props = props.Where(q => !string.IsNullOrEmpty(q.value)).ToList();
            return result;
        }

        protected override dynamic GetModelsByPart(DbRESTFulRepository repository, int pageIndex, int pageSize, string brandCode, string partCode)
        {
            return repository.Invoke(CSIs.Query_Models_By_Part_For_Bjhd, new { pageIndex, pageSize, brandCode, partCode });
        }

        protected override dynamic QueryVinByCode(DbRESTFulRepository repository, Get_Model_InfoParam param)
        {
            return repository.Invoke(CSIs.Query_Vin_By_Code_For_Bjhd, param);
        }

        protected override List<Get_Model_InfoResult._props> GetVinProps(DbRESTFulRepository repository, dynamic vin)
        {
            List<Get_Model_InfoResult._props> retList = new List<Get_Model_InfoResult._props>();
            retList.Add(new Get_Model_InfoResult._props { key = "车型", value = vin.name });
            retList.Add(new Get_Model_InfoResult._props { key = "生产日期", value = vin.productionDate });
            retList.Add(new Get_Model_InfoResult._props { key = "型号代码", value = vin.code });
            retList.Add(new Get_Model_InfoResult._props { key = "国家/地区", value = "中国" });
            retList.Add(new Get_Model_InfoResult._props { key = "发动机", value = vin.engineCode });
            retList.Add(new Get_Model_InfoResult._props { key = "变速箱", value = vin.transCode });
            retList.Add(new Get_Model_InfoResult._props { key = "车身颜色", value = $"{vin.bodyColor}:{vin.bodyColorDesc}" });
            retList.Add(new Get_Model_InfoResult._props { key = "内饰颜色", value = $"{vin.trimColor}:{vin.trimColorDesc}" });
            return retList.Where(q => !string.IsNullOrEmpty(q.value)).ToList();
        }
        protected override List<Get_Model_InfoResult._features> GetVinFeatures(DbRESTFulRepository repository, dynamic vin)
        {
            string featureCodes = vin.featureCodes;
            if (!string.IsNullOrEmpty(featureCodes))
            {
                List<Get_Model_InfoResult._features> retList = new List<Get_Model_InfoResult._features>();
                var featureCodeList = featureCodes.Split(",");
                IEnumerable<Feature> features = repository.Invoke<Feature>(CSIs.Query_Vin_Features_Standard, new { featureCodes = featureCodeList });
                foreach (var feature in features)
                {
                    retList.Add(new Get_Model_InfoResult._features() { key = feature.featureCode, value = feature.featureName });
                }
                return retList;
            }
            else
            {
                return null;
            }

        }
        protected override List<SearchSubGroupResults> GetSearchResults(DbRESTFulRepository repository, string brandCode, string[] partCodes, string selectorId)
        {
            return repository.Invoke<SearchSubGroupResults>(CSIs.Search_SubGroups_By_PartCodes_For_Bjhd, new { brandCode, partCodes, selectorId });
        }
        protected override IEnumerable<dynamic> GetHotPoints(DbRESTFulRepository repository, JObject param)
        {
            return repository.Invoke(CSIs.Query_HotPoints_For_Bjhd, param);
        }

        protected override List<Query_PartsResult> GetParts(DbRESTFulRepository repository, JObject param)
        {
            return repository.Invoke<Query_PartsResult>(CSIs.Query_Parts_For_Bjhd, param);
        }
        protected override List<Query_PartsResult> BuildPartResults(List<Query_PartsResult> result)
        {
            foreach (var info in result)
            {
                info.modelNotes = (info.firstYear + " - " + info.lastYear);
                if (info.modelNotes == " - ") info.modelNotes = "";
                info.modelFilter = string.Join(" > ", info.modelFilter.Split(new char[] { '>' }, StringSplitOptions.RemoveEmptyEntries));
                info.notes = string.Join(" > ", info.notes.Split(new char[] { '>' }, StringSplitOptions.RemoveEmptyEntries));
                info.notes = info.modelFilter + "$$" + info.notes;
                info.modelFilter = "";
                if (info.notes == "$$")
                {
                    info.notes = "";
                }
            }
            return result;
        }
        protected override IEnumerable<Query_SubGroupResult> GetSubGroup(DbRESTFulRepository repository, JObject param)
        {
            return repository.Invoke<Query_SubGroupResult>(CSIs.Query_SubGroup_For_Bjhd, param);
        }
        protected override void FilterPartsByVin(DbRESTFulRepository repository, ref List<Query_PartsResult> result, string vin, string selectorId)
        {
            if (string.IsNullOrEmpty(vin)) return;
            var vinInfo = QueryVinByCode(repository, new Get_Model_InfoParam { vin = vin });
            if (vinInfo == null) return;
            string productionDateStr = vinInfo.productionDate;
            string trimColor = vinInfo.trimColor;
            string bodyColor = vinInfo.bodyColor;
            var vinFeatureList = new HashSet<string>(vinInfo.featureCodes.Split(','));
            int? productionDate = null;
            if (!string.IsNullOrEmpty(productionDateStr))
            {
                productionDate = productionDateStr.ToInt();
            }
            var modelFeature = repository.Invoke(CSIs.Get_Model_Features_By_Vin_For_Bjhd, new { vin });
            if (modelFeature == null || modelFeature.featureCodes == null)
            {
                return;
            }
            string modelFeatureCodes = modelFeature.featureCodes;
            if (string.IsNullOrEmpty(modelFeatureCodes))
            {
                return;
            }
            var modelFeatureList = modelFeatureCodes.Split(',');
            foreach (var info in result)
            {
                if (productionDate.HasValue)
                {
                    if (info.firstYear.HasValue && info.firstYear.Value > productionDate.Value)
                    {
                        info.belongToVin = false;
                        continue;
                    }
                    if (info.lastYear.HasValue && info.lastYear.Value < productionDate.Value)
                    {
                        info.belongToVin = false;
                        continue;
                    }
                }
                if (!ModelFeatureMatch(modelFeatureList, info.modelFilter, '>'))
                {
                    info.belongToVin = false;
                    continue;
                }
                if (!VinFeatureMatch(vinFeatureList, info.featureCodes, '>'))
                {
                    info.belongToVin = false;
                    continue;
                }
            }
            if (!string.IsNullOrEmpty(trimColor))
            {
                var groups = result.Where(q => q.belongToVin).GroupBy(q => q.imageSN);
                foreach (var group in groups)
                {
                    var groupCount = group.Count();
                    if (groupCount > 1)
                    {
                        var trimNotFitGroup = group.Where(q => !string.IsNullOrEmpty(q.trimColor) && q.trimColor != trimColor);
                        var trimNotFitGroupCount = trimNotFitGroup.Count();
                        if (trimNotFitGroupCount > 0 && trimNotFitGroupCount != groupCount)
                        {
                            trimNotFitGroup.ForEach(q => q.belongToVin = false);
                        }
                    }
                }
            }

            if (!string.IsNullOrEmpty(bodyColor))
            {
                var groups = result.Where(q => q.belongToVin).GroupBy(q => q.imageSN);
                foreach (var group in groups)
                {
                    var groupCount = group.Count();
                    if (groupCount > 1)
                    {
                        var bodyNotFitGroup = group.Where(q => !string.IsNullOrEmpty(q.bodyColor) && q.bodyColor != bodyColor);
                        var bodyNotFitGroupCount = bodyNotFitGroup.Count();
                        if (bodyNotFitGroupCount > 0 && bodyNotFitGroupCount != groupCount)
                        {
                            bodyNotFitGroup.ForEach(q => q.belongToVin = false);
                        }
                    }
                }
            }
            result.Where(q => q.belongToVin).ForEach(x => x.sort = x.modelFilter.Split(new char[] { '>' }, StringSplitOptions.RemoveEmptyEntries).Count());
            var groupA = result.Where(q => q.belongToVin).GroupBy(q => q.imageSN);
            foreach(var group in groupA)
            {
                if(group.Count()>1)
                {
                    var maxCount = group.Max(q => q.sort);
                    group.Where(q => q.sort != maxCount).ForEach(x => x.belongToVin = false);
                }
            }

            result.Where(q => q.belongToVin).ForEach(x => x.sort = x.featureCodes.Split(new char[] { '>' }, StringSplitOptions.RemoveEmptyEntries).Count());
            var groupB = result.Where(q => q.belongToVin).GroupBy(q => q.imageSN);
            foreach (var group in groupB)
            {
                if (group.Count() > 1)
                {
                    var maxCount = group.Max(q => q.sort);
                    group.Where(q => q.sort != maxCount).ForEach(x => x.belongToVin = false);
                }
            }
        }

        private bool ModelFeatureMatch(string[] featureList, string featureCodes, char split = ',')
        {
            if (string.IsNullOrEmpty(featureCodes))
            {
                return true;
            }
            var targetList = featureCodes.Split(split);
            for (int i = 0; i < 10; i++)
            {
                if (!string.IsNullOrEmpty(featureList[i]) && !string.IsNullOrEmpty(targetList[i]) && featureList[i] != targetList[i])
                {
                    return false;
                }
            }
            return true;
        }

        private bool VinFeatureMatch(HashSet<string> featureList, string featureCodes, char split = ',')
        {
            if (string.IsNullOrEmpty(featureCodes))
            {
                return true;
            }
            var targetList = featureCodes.Split(new char[] { split}, StringSplitOptions.RemoveEmptyEntries);
            if(targetList.Length == 0)
            {
                return true;
            }
            foreach (var target in targetList)
            {
                if (!featureList.Contains(target))
                {
                    return false;
                }
            }
            return true;
        }

        protected override List<Query_SubGroupResult> FilterSubGroupsByVin(DbRESTFulRepository repository, List<Query_SubGroupResult> results, JObject param)
        {
            var vin = param.Value<string>(ParamFields._vin);
            if (string.IsNullOrEmpty(vin) || results == null || results.Count == 0)
            {
                return results;
            }
            var modelFeature = repository.Invoke(CSIs.Get_Model_Features_By_Vin_For_Bjhd, new { vin });
            if (modelFeature == null || modelFeature.featureCodes == null)
            {
                return results;
            }
            string featureCodes = modelFeature.featureCodes;
            if (string.IsNullOrEmpty(featureCodes))
            {
                return results;
            }
            var featureList = featureCodes.Split(',');
            foreach (var info in results)
            {
                info.belongTo = ModelFeatureMatch(featureList, info.subgroupFilterCode);
            }
            return results;
        }

        protected override List<Query_SubGroupResult> BuildSubGroupResults(List<Query_SubGroupResult> result)
        {
            return result.GroupBy(q => q.id).Select(x => new Query_SubGroupResult { id = x.First().id, code = x.First().code, applicableModel = x.First().applicableModel, description = x.First().description, imageSN = x.First().imageSN, mainGroupCode = x.First().mainGroupCode, mainGroupId = x.First().mainGroupId, name = x.First().name, imageUrl = x.First().imageUrl, belongTo = x.Any(y => y.belongTo) }).ToList();
        }
    }
}



